import pygame
import random
from game_items import *
from game_hud import *
from game_music import *

class Game(object):
    """游戏类"""
    def __init__(self):
       # 游戏主窗口
        
        self.main_window = pygame.display.set_mode(SCREEN_RECT.size)
        pygame.display.set_caption("飞机大战")
        # 游戏状态属性
        
        self.is_game_over = False         #游戏结束标记  
        self.is_pause = False             #游戏暂停标记
                  

        # 精灵组属性
        self.all_group = pygame.sprite.Group()      # 所有精灵组
        self.enemies_group = pygame.sprite.Group()  # 敌机精灵组
        self.supplies_group = pygame.sprite.Group() # 道具精灵组

        # 创建精灵
        # # 背景精灵，向下方移动
        #GameSprite("background.png",1,self.all_group)
        # 修改背景精灵，交替滚动
        self.all_group.add(Background(False),Background(True))

        # self.hero = Plane(1000,5,0,"me_down.wav",
        #                     ["me%d.png" % i for i in range(1,3)],
        #                     "me1.png",
        #                     ["me_destroy_%d.png" % i for i in range(1,5)],self.all_group )
        #self.hero.rect.center = SCREEN_RECT.center      # 显示在屏幕中央

        # 指示器面板
        self.hud_panel = HudPanel(self.all_group)

        # 创建敌机
        self.create_enemies()

        self.hero = Hero(self.all_group)

        self.hud_panel.show_bomb(self.hero.bomb_count)

        self.create_supplies()

        #创建音乐播放器
        self.player = MusicPlayer("game_music.ogg")
        self.player.play_music()

        # # TODO
        # for enemy in self.enemies_group.sprites():
        #     enemy.speed = 0
        #     enemy.rect.y += 400
        # self.hero.speed = 1


    def create_enemies(self):
        count = len(self.enemies_group.sprites())
        groups = (self.all_group, self.enemies_group)
        if self.hud_panel.level == 1 and count == 0:
            for i in range(16):
                Enemy(0,3, *groups)
        elif self.hud_panel.level == 2 and count == 16:
            for enemy in self.enemies_group.sprites():
                enemy.max_speed = 5
            for i in range(8):
                Enemy(0,5, *groups)
            for i in range(2):
                Enemy(1,1, *groups)  
        elif self.hud_panel.level == 3 and count == 26:
            for enemy in self.enemies_group.sprites():
                enemy.max_speed = 7 if enemy.kind == 0 else 3
            for i in range(8):
                Enemy(0,7, *groups)  
            for i in range(2):
                Enemy(1,3, *groups)   
            for i in range(2):
                Enemy(2,1, *groups)
        

    def reset_game(self):
        """重置游戏"""
        
        self.is_game_over = False         # 游戏结束标记
        self.is_pause = False             # 游戏暂停标记
        self.hud_panel.reset_panel()      # 重置指示器面板

        self.hero.rect.midbottom = HERO_DEFAULT_MID_BOTTOM

    def event_handler(self):
        """事件监听"""
        for event  in  pygame.event.get():
            if  event.type == pygame.QUIT:
                return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                 return True
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                if self.is_game_over:    #游戏已经结束
                    self.reset_game()    #游戏已经开始
                else:
                    self.is_pause = not self.is_pause   #切换暂停状态
                    self.player.pause_music(self.is_pause)
            # 判断是否正在游戏
            if not self.is_game_over and not self.is_pause:
                # #监听关闭子弹增强事件
                if event.type == BULLET_ENHANCED_OFF_EVENT:
                    self.hero.bullets_kind = 0
                    pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 0)
                #监听投放道具事件
                if event.type == THROW_SUPPLY_EVENT:
                    self.player.play_sound("supply.wav")
                    supply = random.choice(self.supplies_group.sprites())
                    supply.throw_supply()
                #监听发射子弹事件
                if event.type == HERO_FIRE_EVENT:
                    self.player.play_sound("bullet.wav")
                    self.hero.fire(self.all_group)
                #监听取消英雄飞机无敌的事件    
                if event.type == HERO_POWER_OFF_EVENT:
                    print("取消无敌状态。。。")
                    self.hero.is_power = False
                    pygame.time.set_timer(HERO_POWER_OFF_EVENT,0)
                #监听英雄飞机牺牲事件
                if event.type == HERO_DEAD_EVENT:
                    print("英雄牺牲了。。。")
                    self.hud_panel.lives_count -= 1
                    self.hud_panel.show_lives()
                    self.hud_panel.show_bomb(self.hero.bomb_count)
                
                # 监听玩家按下字母 b ，引爆炸弹
                if event.type == pygame.KEYDOWN and event.key ==pygame.K_b:
                    # TODO 测试炸弹数量变化（# TODO 表示待完成提醒，在vscode里可以查询待做任务）
                    #self.hud_panel.show_bomb(random.randint(0,100))
                    # TODO 测试生命计数数量变化
                    # self.hud_panel.lives_count = random.randint(0,10)
                    # self.hud_panel.show_lives()
                    # TODO 测试停止游戏后是否可以重新开始游戏
                    #self.hud_panel.lives_count = 0
                    # TODO 测试炸毁所有敌机
                    # 引爆炸弹
                    score = self.hero.blowup(self.enemies_group)
                    # 更新炸弹数量显示
                    self.hud_panel.show_bomb(self.hero.bomb_count)
                    # 更新游戏得分
                    if self.hud_panel.increase_score(score):
                        self.create_enemies()
        return False

    def start(self):
        """开始游戏"""
         
        clock = pygame.time.Clock()   #游戏时钟
        frame_counter = 0             # 逐帧动画计数器                    
        while True:                   #开始游戏循环
            # 生命计数等于0，表示游戏结束
            self.is_game_over = self.hud_panel.lives_count == 0                        
            if self.event_handler():  #事件监听    
                self.hud_panel.save_best_score()    
                return
            # 判断游戏状态
            if self.is_game_over:
                
                self.hud_panel.panel_pause(True,self.all_group)
            elif self.is_pause:
                self.hud_panel.panel_pause(False,self.all_group)
            else:
                self.hud_panel.panel_resume(self.all_group)
                # 碰撞检测
                self.check_collide()
                # TODO测试修改游戏得分
                # if self.hud_panel.increase_score(100):
                #     print("升级到 %d" % self.hud_panel.level)
                #     self.create_enemies()
                # TODO 模拟英雄飞机受到伤害
                #self.hero.hp -=30
                keys = pygame.key.get_pressed()
                if keys[pygame.K_RIGHT]:
                    self.hero.rect.x += 10
                # 水平移动
                move_hor = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
                # 垂直
                move_ver = keys[pygame.K_DOWN] - keys[pygame.K_UP]

                # 修改逐帧动画计数器
                frame_counter = (frame_counter + 1) % FRAME_INTERVAL
                # 更新 all_group.update(), 更新所有精灵
                self.all_group.update(frame_counter == 0, move_hor,move_ver)
            # 绘制 all_group 中所有的精灵
            self.all_group.draw(self.main_window)
            pygame.display.update()      #更新显示 
            clock.tick(60)               #设置刷新帧率

    
    
    def check_collide(self):
        if not self.hero.is_power:
            enemies = pygame.sprite.spritecollide(self.hero,self.enemies_group,False,
                                                      pygame.sprite.collide_mask)
            enemies = list(filter(lambda x: x.hp > 0, enemies))
            if enemies:
                #播放英雄被撞毁音效
                self.player.play_sound(self.hero.wav_name)
                self.hero.hp = 0
            for enemy in enemies:
                enemy.hp = 0

    #检测敌机被子弹击中
        hit_enemies = pygame.sprite.groupcollide(self.enemies_group,
                                                self.hero.bullets_group,
                                                False,
                                                False,
                                                pygame.sprite.collide_mask)
        #遍历字典
        for enemy in hit_enemies:
            if enemy.hp <= 0:
                continue
            for bullet in hit_enemies[enemy]:
                bullet.kill()
                enemy.hp -= bullet.damage
                if enemy.hp > 0:
                    continue
                if self.hud_panel.increase_score(enemy.value):
                    #播放升级音效
                    self.player.play_sound("upgrade.wav")
                    self.create_enemies()
                #播放敌机爆炸音效
                self.player.play_sound(enemy.wav_name)
                #退出遍历子弹列表循环
                break  
        # #英雄拾取道具
        supplies = pygame.sprite.spritecollide(self.hero,
                                               self.supplies_group,
                                               False,
                                               pygame.sprite.collide_mask)
        if supplies:
            supply = supplies[0]
            #播放使用道具音效
            self.player.play_sound(supply.wav_name)
            #将道具设置到游戏窗口下方
            supply.rect.y = SCREEN_RECT.h
            #判断道具类型
            if supply.kind == 0:
                self.hero.bomb_count += 1
                self.hud_panel.show_bomb(self.hero.bomb_count)
            else:
                self.hero.bullets_kind = 1
                #设置关闭子弹增强的定时器事件
                pygame.time.set_timer(BULLET_ENHANCED_OFF_EVENT, 20000)

    def create_supplies(self):
        #创建道具
        Supply(0, self.supplies_group, self.all_group)
        Supply(1, self.supplies_group, self.all_group)
        #设置30s投放道具定时器事件
        pygame.time.set_timer(THROW_SUPPLY_EVENT, 1000)

if __name__ == "__main__":
    pygame.init()  #初始化pygame
    Game().start()  #通过Game()创建对象并调用start方法开始游戏
    pygame.quit()   #退出pygame

     

    


